

#include "WCI.h"
#include "WCIPrivate.h"

#include "Fifo.h"
#include "fm175xx.h"

static WCI *gWCI;

static uint8_t wciFifoBuffer[256];

static fifo_t wciFifo = {
	.out = 0,
	.in = 0,
	.size = sizeof(wciFifoBuffer),
	.buffer = wciFifoBuffer,
};


void WCI_Register(WCI* wci){
	gWCI = wci;
}

void WCI_Init(void){
//		FM175xx_Init();
}


void WCI_InitTime(WciTime_T* time,  unsigned int waitTime, unsigned int guardTime) {
	time->waitTime = waitTime;
	time->guardTime = guardTime;
}


int WCI_SetMode(WCI * wci, int mode)
{
#if 0
	if (wci && wci->ops && wci->ops->setMode) {
		return wci->ops->setMode(wci, mode);
	}
	return -1;
#endif 
	if(gWCI){
		return gWCI->ops->setMode(gWCI, mode);
	}
	return -1;
}

int WCI_Config(WCI * wci, int config)
{
	if(gWCI){
		return gWCI->ops->config(gWCI, config);
	}
	return -1;
}

void WCI_SetRf(WCI* wci, uint8_t state){
	if(state){
		WCI_Config(gWCI, WCI_Cfg_RfOn);
	}
	else{
		WCI_Config(gWCI, WCI_Cfg_RfOff);
	}
}

int WCI_ReadFifo(WCI* wci, uint8_t buf[], uint16_t len) {
	return Fifo_GetBlock(&wciFifo, buf, len);
}

int WCI_FifoSpace(WCI* wci) {
	return Fifo_GetFreeSpace(&wciFifo);
}

int WCI_FifoLength(WCI* wci) {
	return Fifo_GetDataLength(&wciFifo);
}

int WCI_ClearFifo(WCI* wci) {	
	Fifo_Clean(&wciFifo);
	return 0;
}

int WCI_WriteFifo(WCI* wci, uint8_t buf[], uint16_t len) {
	return Fifo_PutBlock(&wciFifo, buf, len);
}

#if 0
int WCI_ReadFifo(WCI* wci, uint8_t buf[], uint16_t len) {
	return WCI_Check(wci, readFifo) ? wci->ops->readFifo(wci, buf, len) : -1;
}

int WCI_FifoSpace(WCI* wci) {
	return WCI_Check(wci, fifoSpace) ? wci->ops->fifoSpace(wci) : -1;
}

int WCI_FifoLength(WCI* wci) {
	return WCI_Check(wci, fifoLength) ? wci->ops->fifoLength(wci) : -1;
}
#endif 

int WCI_Command(WCI* wci,uint8_t cmd, WciTime_T* time, void* param) {
	if(gWCI){
		return gWCI->ops->command(gWCI, cmd, time, param);
	}
	return -1;
//		return WCI_Check(wci, command) ? wci->ops->command(wci,cmd, time, param) : -1;
}


// int WCI_Prepare(WCI*wci, unsigned char* buf, unsigned int len) {
// 	if (wci&&wci->ops&&wci->ops->prepare) {
// 		return wci->ops->prepare(wci, buf, len);
// 	}
// 	return -1;
// }

int WCI_Exchange(WCI* wci, unsigned char* tx, unsigned tlen,
	unsigned char* rx, unsigned *rlen, unsigned rmax,
	unsigned waitTime, unsigned int guardTime)
{
	int rxLength;
	int ret;
	WciBits_T wciBits = { 0, 0 };

	ret = WCI_ClearFifo(wci);
	if (ret < 0){
		return ret;
	}
	ret = WCI_WriteFifo(wci, tx, tlen);
	if (ret < 0){
		return ret;
	}

	ret = WCI_Command(wci, WCI_Cmd_Exchagne, &(WciTime_T){waitTime, guardTime}, &wciBits);
	rxLength = WCI_FifoLength(wci);
	if (rxLength > rmax) {
		return WCI_S_OverRun;
	}
	WCI_ReadFifo(wci, rx, rxLength);
	*rlen = rxLength;
	return ret;
}

int WCI_ExchangeBit(WCI* wci, unsigned char* tx, unsigned int tlen, unsigned int tbits,
	unsigned char* rx, unsigned int* rlen, unsigned int *rbits, unsigned int rmax,
	unsigned int wTime, unsigned int gTime) {
	int rxLength;
	int ret;
	WciBits_T wciBits;


	ret = WCI_ClearFifo(wci);
	if(ret < 0){
		return ret;
	}
	ret = WCI_WriteFifo(wci, tx, tlen);
	if(ret < 0){
		return ret;
	}
	wciBits.lastTx = tbits;
	wciBits.lastRx = *rbits;
	ret = WCI_Command(wci, WCI_Cmd_Exchagne, &(WciTime_T){wTime, gTime}, &wciBits);
	rxLength = WCI_FifoLength(wci);
	*rbits = wciBits.lastRx;
	if (rxLength > rmax) {
		return WCI_S_OverRun;
	}
	WCI_ReadFifo(wci, rx, rxLength);
	*rlen = rxLength;
	return ret;
}

int WCI_Support(WCI * wci)
{
	if (gWCI) {
		return gWCI->support;
	}
	return 0;
}


#if 0
int WCI_Control(WCI * wci, unsigned char ctrl, unsigned char * pin, unsigned int ilen, unsigned char * pout, unsigned int * olen)
{
	if (wci&&wci->ops&&wci->ops->control) {
		return wci->ops->control(wci, ctrl, pin, ilen, pout, olen);
	}
	return -1;
}
#endif 

